Skip to content

atunnel: broker actor certificates through atelet - #708

Merged
Lior Lieberman (LiorLieberman) merged 4 commits into
agent-substrate:mainfrom
kagent-dev:issue-706-atunnel-identity
Aug 7, 2026
Merged

atunnel: broker actor certificates through atelet#708
Lior Lieberman (LiorLieberman) merged 4 commits into
agent-substrate:mainfrom
kagent-dev:issue-706-atunnel-identity

Conversation

@EItanya

@EItanya Eitan Yarmush (EItanya) commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Closes #706

Summary

  • broker short-lived actor certificates from atelet over a same-node mTLS Unix socket
  • keep the actor private key in atunnel and renew the certificate before expiry
  • authenticate egress CONNECT using the actor certificate instead of bearer tokens

Testing

  • make verify
  • go test -race ./internal/atunnel

@LiorLieberman

Copy link
Copy Markdown
Collaborator

Thanks Eitan Yarmush (@EItanya) !

Quick question before I review more deeply today.

With the goal of "having a JWT available to atunnel to append on a CONNECT request to the egress" -- What parts of the this PR addresses?

Here are the parts we needed (before this pr -- havent reviewed it yet);

  1. Improve the JWT issuance flow as part of MintJWT (properly authorize atelets, having the JWT formats solid, etc)
  2. Implement an in-memory cache with go background routine that refreshes certs for every active actor.
  3. Implement the UDS socket between atunnel and atelet to pass the certs+jwts.

From a very brief glance - I think your PR is attempting to do all three. Is that correct?

Also, For (1), we likely need to sort out two things to make the JWTs useful:

  • Get the issuer a publicly accessible DNS name that is also oidc-compliant (cc: Taahir Ahmed (@ahmedtd))
  • Agree on the format for the Subject field on JWTs

See for ref -

// TODO: This is currently API but it has to be a globally unique, oidc-compliant and accsible DNS name
Issuer: "https://api.ate-system.svc",
// TODO: this format is very likely going to change.
Subject: fmt.Sprintf("atespaces:%s:actors:%s", req.GetAtespace(), req.GetActorName()),

@EItanya

Copy link
Copy Markdown
Collaborator Author

Yes, with two clarifications: this PR renews JWTs, not actor certificates, and each worker has only one active actor.

  1. JWT issuance/authorization: implemented. Atunnel authenticates to atelet over mTLS using the worker Pod identity. Atelet derives the worker UID from that certificate and resolves its current actor assignment; the request does not supply actor identity. Ateapi then independently revalidates the atelet’s node, worker assignment, actor UID, and permitted audience before minting. The JWT includes the actor UID/resource version and worker Pod UID.

  2. In-memory renewal: implemented for the worker’s single active actor. Atunnel mints before activation, stores the JWT in memory, renews with roughly 10% lifetime remaining, retries until expiry, and fails closed for new tunnels after expiry. Deactivation clears the JWT and stops renewal.

  3. UDS broker: implemented. The UDS carries only JWT requests/responses—not certificates. The Pod certificate is used to mutually authenticate the atunnel↔atelet connection, including verifying both are on the same node.

I agree the issuer and subject contracts remain unresolved. This PR intentionally retains the existing issuer/subject behavior and does not implement PEP verification yet. Before verification lands, we need a stable OIDC issuer with discovery/JWKS reachable by the PEP.

@EItanya Eitan Yarmush (EItanya) changed the title atunnel: broker actor JWTs through atelet atunnel: broker actor certificates through atelet Aug 4, 2026
Comment thread cmd/ateapi/internal/actoridentity/actoridentity.go Outdated
Comment thread cmd/ateapi/main.go
Comment thread cmd/atelet/credentialbroker.go Outdated
Comment thread cmd/atelet/credentialbroker.go Outdated
Comment on lines +40 to +44
// TODO: Before release, request an atunnel-specific MintCert purpose and
// require the egress PEP to reject generic actor certificates.
// The request deliberately carries no actor identity. The authenticated Pod
// UID is the only input used to select a worker and its current assignment.
workerUID, err := authenticatedWorkerUID(ctx)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I am following the TODO comment. I thought we were saying that we need it to be an actor cert thats specifically for atunnel use.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be fine to merge without that, and then add it in a follow up? Either way works.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. MintCert now requires the ATUNNEL purpose, embeds it in the ActorIdentity certificate extension, and atunnel verifies it before installing the certificate. PEP-side purpose enforcement remains a before-release follow-up.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[needs issue] Eitan Yarmush (@EItanya) do we need an issue for that?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can create one, but really this should just go straight into your PR

Comment thread cmd/atelet/credentialbroker.go Outdated
Comment thread cmd/ateom-microvm/restore.go
Comment thread internal/ateompath/ateompath.go
Comment thread internal/atunnel/credential.go
Comment thread internal/atunnel/egress.go
Comment thread internal/proto/ateletpb/atelet.proto
Comment thread pkg/proto/ateapipb/ateapi.proto Outdated
Comment thread cmd/ateapi/internal/actoridentity/actoridentity.go
Comment thread cmd/atelet/credentialbroker.go Outdated
Comment on lines +40 to +44
// TODO: Before release, request an atunnel-specific MintCert purpose and
// require the egress PEP to reject generic actor certificates.
// The request deliberately carries no actor identity. The authenticated Pod
// UID is the only input used to select a worker and its current assignment.
workerUID, err := authenticatedWorkerUID(ctx)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be fine to merge without that, and then add it in a follow up? Either way works.

Comment thread cmd/atelet/credentialbroker.go Outdated
Comment thread cmd/atelet/main.go
Comment thread cmd/atelet/main.go Outdated
serverboot.Fatal(ctx, "Failed to load atelet Pod identity", fmt.Errorf("credential bundle has no Pod identity"))
}
brokerTLS := tlsCfg.Clone()
brokerTLS.VerifyConnection = restrictClientToNode(ateletIdentity)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think over a UDS we should be able to get this level of control just from filesystem permissions? Ie, we create a UDS socket file for each individual ateom, and make sure only that ateom can access it.

TLS over a UDS is a bit strange.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, we can do that. To get the same isolation from filesystem permissions, though, we would need a separate broker hostPath, mount only each worker’s own socket directory into its ateom, and manage one listener per worker. The current hostPath is shared by all root-running ateoms, so 0600 on a per-worker filename alone would not isolate them.

mTLS gives us the same worker-to-atelet binding with considerably less change in the current layout. Would you be okay with keeping mTLS here?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[needs issue] lets open an for that

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracking this investigation in #778: #778

Comment thread internal/atunnel/egress.go
@EItanya
Eitan Yarmush (EItanya) force-pushed the issue-706-atunnel-identity branch 2 times, most recently from 960bb6d to 03aac19 Compare August 5, 2026 17:01
@EItanya

Copy link
Copy Markdown
Collaborator Author

Correction to my earlier summary: this PR has been retooled from bearer JWTs to purpose-scoped actor certificates. Atunnel generates and retains a per-activation private key, sends only a CSR to the node-local atelet, and atelet asks ateapi to mint an ATUNNEL-purpose actor certificate after revalidating the exact worker assignment. Atunnel renews that certificate in memory; no actor JWT is transported, so JWT issuer/subject work is no longer in scope here. PEP-side purpose enforcement remains a before-release follow-up.

Comment thread internal/atunnel/egress.go Outdated
Comment thread internal/proto/ateompb/ateom.proto
Comment thread internal/atunnel/egress.go
Comment thread cmd/atelet/credentialbroker.go Outdated
Comment thread internal/atunnel/egress.go
Comment thread internal/atunnel/credential.go
@ahmedtd

Copy link
Copy Markdown
Collaborator

LGTM for the certificate bits.

@bowei Bowei Du (bowei) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

look ok. I think we might want to clean up some of the API comments + make sure optional vs required is what we want.

Comment thread pkg/proto/ateapipb/ateapi.proto Outdated
Comment thread internal/proto/ateompb/ateom.proto
Comment thread internal/proto/ateompb/ateom.proto Outdated
Comment thread internal/proto/ateletpb/atelet.proto
@LiorLieberman

Copy link
Copy Markdown
Collaborator

LGTM
Will merge once workflows are done.

Eitan Yarmush (@EItanya) please open the issues here (added [needs issue] tag)

Also we want to remove the egressgatewayadress flag and replace it with a proper proto on the actor.

@LiorLieberman
Lior Lieberman (LiorLieberman) merged commit c9777b4 into agent-substrate:main Aug 7, 2026
13 of 15 checks passed
@EItanya
Eitan Yarmush (EItanya) deleted the issue-706-atunnel-identity branch August 7, 2026 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Broker actor JWTs from atelet to atunnel over an authenticated Unix socket

5 participants